Symfony's Controller Layer
Chapter 6 - Inside The Controller Layer
Reading material at
here Key Components
- Front Controller
- Actions
- sfRequest
- sfResponse
- sfUser
- Filters
Unique Entry Point
<?php
require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
$configuration = ProjectConfiguration
::getApplicationConfiguration('frontend', 'prod', false);
sfContext
::createInstance($configuration)->dispatch();
Jobs
- Load the project configuration class and the symfony libraries.
- Create an application configuration and a symfony context.
- Load and initiate the core framework classes.
- Load the configuration.
- Decode the request URL to determine the action to execute and the request parameters.
- If the action does not exist, redirect to the 404 error action.
- Activate filters (for instance, if the request needs authentication).
- Execute the filters, first pass.
- Execute the action and render the view.
- Execute the filters, second pass.
- Output the response.
class mymoduleActions extends sfActions
{
public function executeIndex()
{
// ...
}
public function executeList()
{
// ...
}
public function executeDelete()
{
// ...
}
}
Alternative Syntax
class indexAction extends sfAction
{
public function execute($request)
{
// ...
}
}
class listAction extends sfAction
{
public function execute($request)
{
// ...
}
}
Accessing Information
class mymoduleActions extends sfActions
{
public function executeIndex($request)
{
// Retrieving request parameters
$password = $request->getParameter('password');
// Retrieving controller information
$moduleName = $this->getModuleName();
$actionName = $this->getActionName();
// Retrieving framework core objects
$userSession = $this->getUser();
$response = $this->getResponse();
$controller = $this->getController();
$context = $this->getContext();
// Setting action variables to pass information to the template
$this->setVar('foo', 'bar');
$this->foo = 'bar'; // Shorter version
}
}
Accessing Info
Name |
Function |
Sample Output |
Request Information |
|
|
isMethod($method) |
Is it a post or a get? |
true or false |
getMethod() |
Request method name |
'POST' |
getHttpHeader('Server') |
Value of a given HTTP header |
'Apache/2.0.59 (Unix) DAV/2 PHP/5.1.6' |
getCookie('foo') |
Value of a named cookie |
'bar' |
isXmlHttpRequest() * |
Is it an Ajax request? |
true |
isSecure() |
Is it an SSL request? |
true |
Request Parameters |
|
|
hasParameter('foo') |
Is a parameter present in the request? |
true |
getParameter('foo') |
Value of a named parameter |
'bar' |
getParameterHolder()->getAll() |
Array of all request parameters |
|
URI-Related Information |
|
|
getUri() |
Full URI |
'http://localhost/frontend_dev.php/mymodule/myaction' |
getPathInfo() |
Path info |
'/mymodule/myaction' |
getReferer() ** |
Referrer |
'http://localhost/frontend_dev.php/' |
getHost() |
Host name |
'localhost' |
getScriptName() |
Front controller path and name |
'frontend_dev.php' |
Client Browser Information |
|
|
getLanguages() |
Array of accepted languages |
Array( [0] => fr [1] => fr_FR [2] => en_US [3] => en ) |
getCharsets() |
Array of accepted charsets |
Array( [0] => ISO-8859-1 [1] => UTF-8 [2] => * ) |
getAcceptableContentTypes() |
Array of accepted content types |
Array( [0] => text/xml [1] => text/html |
Files
class mymoduleActions extends sfActions
{
public function executeUpload($request)
{
if ($request->hasFiles())
{
foreach ($request->getFileNames() as $uploadedFile)
{
$fileName = $request->getFileName($uploadedFile);
$fileSize = $request->getFileSize($uploadedFile);
$fileType = $request->getFileType($uploadedFile);
$fileError = $request->hasFileError($uploadedFile);
$uploadDir = sfConfig::get('sf_upload_dir');
$request->moveFile($uploadedFile, $uploadDir.'/'.$fileName);
}
}
}
}
Termination
Default:
return sfView::SUCCESS;
return sfView::ERROR;
return 'error';
return 'myResult'
return sfView::NONE;
No template?
public function executeIndex()
{
$this->getResponse()->setContent("<html><body>Hello, World!</body></html>");
return sfView::NONE;
}
// Is equivalent to
public function executeIndex()
{
return $this->renderText("<html><body>Hello, World!</body></html>");
}
Only Header?
public function executeRefresh()
{
$output = '<"title","My basic letter"],["name","Mr Brown">';
$this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');
return sfView::HEADER_ONLY;
}
Change Template
$this->setTemplate('myCustomTemplate');
using another action
$this->forward('otherModule', 'index');
$this->redirect('otherModule/index');
$this->redirect('http://www.google.com/');
404
public function executeShow($request)
{
$article = ArticlePeer::retrieveByPK($request->getParameter('id'));
if (!$article)
{
$this->forward404();
}
}
// This action is equivalent to the one shown in Listing 6-11
public function executeShow($request)
{
$article = ArticlePeer::retrieveByPK($request->getParameter('id'));
$this->forward404If(!$article);
}
// So is this one
public function executeShow()
{
$article = ArticlePeer::retrieveByPK($request->getParameter('id'));
$this->forward404Unless($article);
}
Fragmentation
class mymoduleActions extends sfActions
{
public function preExecute()
{
// The code inserted here is executed at the beginning of each action call
...
}
...
public function postExecute()
{
// The code inserted here is executed at the end of each action call
...
}
In Actions
object of class sfUser
access:
$this->getUser()
set/get
$this->getUser()->setAttribute('nickname', $nickname);
...
$this->getUser()->getAttributeHolder()->remove('nickname');
...........
$this->getUser()->getAttributeHolder()->clear();
$nickname = $this->getUser()->getAttribute('nickname', 'Anonymous Coward');
in Templates
<p>
Hello,
<?php echo $sf_user->getAttribute('nickname') ?>
</p>
Flash Attributes
$this->getUser()->setFlash('notice', $value);
........
$this->getUser()->getFlash('notice', $default);
Management
apps/frontend/config/factories.yml
all
:
storage
:
class: sfSessionStorage
param
:
session_name: my_cookie_name
store in DB?
all:
storage:
class: sfMySQLSessionStorage
param:
db_table: session # Name of the table storing the sessions
database: propel # Name of the database connection to use
# Optional parameters
db_id_col: sess_id # Name of the column storing the session id
db_data_col: sess_data # Name of the column storing the session data
db_time_col: sess_time # Name of the column storing the session timestamp
frontend/config/filters.yml
rendering: ~
security: ~
# Generally, you will want to insert your own filters here
cache: ~
common: ~
execution: ~
Your own Filter
class sfGoogleAnalyticsFilter extends sfFilter
{
public function execute($filterChain)
{
// Nothing to do before the action
$filterChain->execute();
// Decorate the response with the tracker code
$googleCode = '
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct="UA-'.$this->getParameter('google_id').'";urchinTracker();
</script>';
$response = $this->getContext()->getResponse();
$response->setContent(str_ireplace('</body>', $googleCode.'</body>',$response->getContent()));
}
}
Some times you need to restrict access to some module/actions.
Certain people have access to a specific action.
Who are certain people?
We define them in sfUser by using
credentials
Define/Manage Credentials
$user = $this->getUser();
// Add one or more credentials
$user->addCredential('foo');
$user->addCredentials('foo', 'bar');
// Check if the user has a credential
echo $user->hasCredential('foo'); => true
// Check if the user has both credentials
echo $user->hasCredential(array('foo', 'bar')); => true
// Check if the user has one of the credentials
echo $user->hasCredential(array('foo', 'bar'), false); => true
// Remove a credential
$user->removeCredential('foo');
echo $user->hasCredential('foo'); => false
// Remove all credentials (useful in the logout process)
$user->clearCredentials();
echo $user->hasCredential('bar'); => false
}
Secure Actions
Option 1: put credentials checking in your code
class mymoduleActions extends sfActions
{
public function executeIndex()
{
$this->forward404Unless($this->getUser()->hasCredential('cred'));
// ...
}
Option 2
apps/frontend/modules/mymodule/config/security.yml
read:
is_secure: off # All users can request the read action
update:
is_secure: on # The update action is only for authenticated users
delete:
is_secure: on # Only for authenticated users
credentials: admin # With the admin credential
all:
is_secure: off # off is the default value anyway